package com.glodon.zhuanli.common;

import com.glodon.framework.common.id.UUIDGenerator;
import com.glodon.framework.common.util.FileUtils2;
import com.glodon.framework.web.util.EnvironmentUtil;
import com.glodon.infrastructure.support.attachment.entity.Attachmentinfo;
import com.glodon.infrastructure.support.attachment.service.AttachmentinfoService;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.FileCopyUtils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;

@Service
@Slf4j
public class LocalFileServiceImpl implements EnvironmentAware , InitializingBean {

	public static final String LOCAL_FILE_ROOT_PARAM = "file" ;
	/**
	 * uuid生成器
	 */
	private UUIDGenerator uuidGenerator = new UUIDGenerator() ;

	private String defaultRootDirectory ;

	//自定义的文件上传位置
	private Map<String, String> rootDirectoryMap = Maps.newHashMap() ;

	@Autowired
	private AttachmentinfoService attachmentinfoService ;

	private Environment environment ;


	public void setEnvironment(Environment environment) {
		this.environment = environment ;
	}

	@Override
	public void afterPropertiesSet() throws Exception {

		this.defaultRootDirectory = FileUtils2.getUserDirectoryPath() ;

		//获取其他的ali库地址
		Map<String, String> properties = EnvironmentUtil.getPropertiesByPrefix( environment, LOCAL_FILE_ROOT_PARAM ) ;

		if(properties!=null&&properties.size()>0){

			for (Map.Entry<String, String> entry : properties.entrySet()) {
				//获取目录key名称
				String key = entry.getKey().replace(LOCAL_FILE_ROOT_PARAM+"." , "") ;
				if(StringUtils.isBlank(key)){
					continue ;
				}
				rootDirectoryMap.put(key.trim() , entry.getValue()) ;
			}

			log.info("local file 目录映射信息{}" , rootDirectoryMap);
		}
	}

	/**
	 * 获取文件后缀
	 * @param filepath
	 * @return
	 */
	public String getFilePostfix(String filepath) {
		if(filepath.lastIndexOf('.')>-1){
			int fileSuffix = filepath.lastIndexOf('.') ;
			return filepath.substring(fileSuffix) ;
		}
		return "" ;
	}
	/**
	 * 获取文件目录
	 * @param type
	 * @return
	 */
	public String getFileDirectory(String type) {
		String dir = "" ;

		if(StringUtils.isBlank(type) || !rootDirectoryMap.containsKey(type)){
			if(StringUtils.isNotBlank(defaultRootDirectory)){
				dir = defaultRootDirectory ;
			}
		}else{
			dir = rootDirectoryMap.get(type) ;
		}

		return dir ;
	}
	
	/**
	 * 格式化文件名称
	 * @param filepath
	 * @return
	 */
	public String formatFileName(String filepath){
		if(filepath.lastIndexOf('.')>-1){
			int fileSuffix = filepath.lastIndexOf('.') ;
			int fileNamePrefix = filepath.lastIndexOf('/')==-1 ?
					(filepath.lastIndexOf("\\") ==-1 ? 0 : filepath.lastIndexOf("\\")) : filepath.lastIndexOf('/') ;
			//文件名称由uuid和当前时间组成
			filepath = filepath.substring(0,fileNamePrefix)+
					uuidGenerator.getNextId()+
					filepath.substring(fileSuffix) ;
			
			return filepath ;
		}
		return filepath ;
	}
	/**
	 * 格式化远程文件
	 * @param filepath
	 * @return
	 */
	public String formateRemoteFile(String filepath , String type){
		//构建文件上传路径
		String directory = getFileDirectory(type) ;
		String remoteFilePath  ;

		if(StringUtils.isBlank(directory)){
			remoteFilePath = "" ;
		}else{
			remoteFilePath = directory+ File.separator ;
		}

		//构建完整路径
		remoteFilePath += filepath.trim() ;
        
        remoteFilePath = remoteFilePath.replaceAll("/+", "/") ;
        
        log.info("文件路径 {}" , remoteFilePath) ;
        
        //替换多余的文件分隔符
        return remoteFilePath ;
	}

	@Transactional
	public Attachmentinfo upload(InputStream inputStream, String filename, String type , String businessId)
			throws IOException {
		return this.upload(inputStream,filename,type,businessId,"");

	}
	@Transactional
	public Attachmentinfo upload(InputStream inputStream, String filename, String type , String businessId ,String remark)
			throws IOException {
		if(inputStream==null||filename==null){
			return null ;
		}
		//格式化文件名称
		String formatedFilepath = formatFileName(filename) ;
		//构建文件上传路径
		String remoteFilePath = formateRemoteFile( formatedFilepath , type ) ;
//		// 创建上传Object的Metadata
//		ObjectMetadata meta = new ObjectMetadata();
//		// 必须设置ContentLength
//		long contentlength = inputStream.available() ;
//		meta.setContentLength(inputStream.available());
//		// 上传Object.
//		ossClient.putObject(namespace, remoteFilePath, inputStream, meta);
//		//关闭文件输入流
//		inputStream.close();

		File targetFile = new File( remoteFilePath ) ;
		if( targetFile.exists() ){
			targetFile.delete() ;
		}
		FileUtils2.copyToFile( inputStream , targetFile ) ;

		IOUtils.closeQuietly( inputStream );

		//在附件信息表中创建附件信息
		Attachmentinfo attachmentinfo = new Attachmentinfo() ;
		attachmentinfo.setOldname(filename) ;
		attachmentinfo.setNewname(formatedFilepath) ;
		attachmentinfo.setFilesize(targetFile.length()) ;
		attachmentinfo.setFormat(getFilePostfix(filename)) ;
		attachmentinfo.setType(type);
		attachmentinfo.setAttachment(remoteFilePath) ;
		attachmentinfo.setBusinessId(businessId);
		attachmentinfo.setRemark(remark);
		attachmentinfo.setDownloadNums(0L);
		//保存附件信息
		attachmentinfoService.save(attachmentinfo);

		return attachmentinfo ;
	}

	public byte[] download(String filepath, String type) throws IOException {
		if(StringUtils.isBlank(filepath)){
			return null ;
		}
		//构建文件下载路径
//        String remoteFilePath = formateRemoteFile(filepath , type) ;
		String remoteFilePath = filepath ;
        // 获取Object，返回结果为OSSObject对象
       try {
//    	   OSSObject object = ossClient.getObject(namespace, remoteFilePath);
//           //验证是否查询到了文件 如果未查询到 则直接返回空
//           if(object==null){
//               return null;
//           }
//           // 获取Object的输入流
//           InputStream objectContent = object.getObjectContent() ;

           File targetFile = new File(remoteFilePath) ;
           if( !targetFile.exists() ){
           	return null ;
		   }
           
           return FileCopyUtils.copyToByteArray(targetFile) ;
		} catch (Exception e) {
		   log.error("获取下载文件流，出现异常。" , e);
			return null;
		}
	}

	public boolean delete(String filepath, String type) {
		//构建文件下载路径
        String remoteFilePath = formateRemoteFile(filepath , type) ;

		FileUtils2.deleteQuietly( new File(remoteFilePath) ) ;

		return true ;
	}

}
